10 REM *** (FFT9-01.BAS) Q = 2^N POINT FFT ***

12 CLS : PRINT : PRINT "INPUT NUMBER OF DATA POINTS AS 2^N"

14 INPUT "N = "; N

16 Q = 2 ^ N: Q1 = Q - 1: N1 = N - 1

18 Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1: Q8 = Q / 8

20 DIM C(Q), S(Q), KC(Q), KS(Q)

22 PI = 3.141592653589793#: P2 = 2 * PI: K1 = P2 / Q

24 '  **** TWIDDLE FACTOR TABLE GENERATION ****

26 FOR I = 0 TO Q: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I)

IF ABS(KC(I)) < .0000005 THEN KC(I) = 0 ' CLEANUP TABLE

IF ABS(KS(I)) < .0000005 THEN KS(I) = 0

NEXT I

28 FOR I = 1 TO Q1: INDX = 0

30 FOR J = 0 TO N1

32 IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N1 - J)

34 NEXT J

36 IF INDX > I THEN SWAP KC(I), KC(INDX): SWAP KS(I), KS(INDX)

38 NEXT I

40 CLS

50 PRINT SPC(30); "MAIN MENU": PRINT : PRINT

60 PRINT SPC(5); "1 = ANALYZE Q/2 COMPONENT TRIANGLE": PRINT

62 PRINT SPC(5); "2 = INVERSE TRANSFORM": PRINT

64 PRINT SPC(5); "3 = EXIT": PRINT

70 PRINT SPC(10); "MAKE SELECTION :";

80 A$ = INKEY$: IF A$ = "" THEN 80

90 A = VAL(A$): ON A GOSUB 600, 700, 990

95 GOTO 40

100 REM *** FFT ***

102 CLS : PRINT "FREQ   F(COS)       F(SIN)       ";

104 PRINT "FREQ   F(COS)       F(SIN)": PRINT : PRINT

106 T9 = TIMER

110 REM *** FFT ROUTINE ***

112 FOR M = 0 TO N1: QT = 2 ^ (N - M): QT1 = QT - 1

114 QT2 = QT / 2: QT3 = QT2 - 1: KT = 0

116 REM *** UNIVERSAL BUTTERFLY ***

118 FOR J = 0 TO Q1 STEP QT: KT2 = KT + 1

120 FOR I = 0 TO QT3: J1 = I + J: K = J1 + QT2

122 CTEMP = (C(J1) + C(K) * KC(KT) - K6 * S(K) * KS(KT)) / SK1

124 STEMP = (S(J1) + K6 * C(K) * KS(KT) + S(K) * KC(KT)) / SK1

126 CTEMP2 = (C(J1) + C(K) * KC(KT2) - K6 * S(K) * KS(KT2)) / SK1

128 S(K) = (S(J1) + K6 * C(K) * KS(KT2) + S(K) * KC(KT2)) / SK1

130 C(K) = CTEMP2: C(J1) = CTEMP: S(J1) = STEMP

132 NEXT I

134 KT = KT + 2: NEXT J

136 NEXT M

140 ' ***  BIT REVERSAL FOR FINAL DATA ***

142 FOR I = 1 TO Q1: INDX = 0

144 FOR J = 0 TO N1

146 IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N1 - J)

148 NEXT J

150 IF INDX > I THEN SWAP C(I), C(INDX): SWAP S(I), S(INDX)

152 NEXT I

160 T9 = TIMER - T9

200 ' ********  DISPLAY ROUTINE  **********

210 FOR Z = 0 TO Q2 - 1

215 GOSUB 300

220 NEXT Z

222 PRINT : PRINT "TIME ="; T9

225 PRINT : PRINT : INPUT "C/R TO CONTINUE:"; A$

230 RETURN

300 PRINT USING "####"; Z; : PRINT "   ";

310 PRINT USING "+##.######"; C(Z); : PRINT "    ";

312 PRINT USING "+##.######"; S(Z); : PRINT "      ";

320 PRINT USING "####"; Z + Q2; : PRINT "   ";

322 PRINT USING "+##.######"; C(Z + Q2); : PRINT "    ";

324 PRINT USING "+##.######"; S(Z + Q2)

330 RETURN

400 REM GENERATE Q/2 COMPONENT TRIANGLE WAVE

T8 = TIMER + 1: DISFLG = 1

408 IF Q / 2 > 1024 THEN QT = 1024 ELSE QT = Q / 2

410 FOR I = 0 TO Q: C(I) = 0: S(I) = 0

420 FOR J = 1 TO QT STEP 2: C(I) = C(I) + COS(K1 * J * I) / (J * J): NEXT

422 IF TIMER > T8 THEN GOSUB 500

430 NEXT I

440 RETURN

500 REM *** BLINK WAIT MESSAGE ***

510 DISFLG = 1 - DISFLG

520 IF DISFLG = 1 THEN CLS : GOTO 550

530 LOCATE 10, 22

540 PRINT "PREPARING DATA - PLEASE WAIT"

550 T8 = TIMER + 1: RETURN

600 REM * Q/2 COMPONENT TRIANGLE *

602 CLS : PRINT : PRINT

604 'PRINT "PREPARING DATA INPUT - PLEASE WAIT!"

610 GOSUB 400

612 SK1 = 2: K6 = 1

614 PRINT : INPUT "DATA READY - C/R TO CONTINUE"; A$

620 GOSUB 100

630 RETURN

700 REM *** INVERSE TRANSFORM ***

710 SK1 = 1: K6 = -1

712 CLS : PRINT "TIME    AMPLITUDE   NOT USED     ";

714 PRINT "TIME   AMPLITUDE     NOT USED": PRINT : PRINT

720 GOSUB 106

730 RETURN

990 END: STOP



